#ifndef AER_STACKALLOCATOR_HPP_
#define AER_STACKALLOCATOR_HPP_

#include "../aerDefs.hpp"


namespace aer {

/// Allow to allocate a large batch of memory in one time
/// [cf. base on Game Engine Architecture]
class StackAllocator
{
  public:
    typedef U32 Marker;
    
    
  private:
    void*  m_data;
    U32    m_byteSize;
    Marker m_top;
    
    
  public:
    explicit 
    StackAllocator(const U32 byteSize)
        : m_data(NULL),
          m_byteSize(byteSize),
          m_top(0u)
    {
      m_data = calloc( 1, m_byteSize);
      AER_ASSERT( NULL != m_data );//
    }
    
    ~StackAllocator()
    {
      AER_SAFE_FREE( m_data );
    }
    
    
    /// Allocates a new block of byteSize from the top;
    /// returns NULL if there is no enough memory
    void* allocate(const U32 byteSize);
    
    /// Aligned allocation. 'alignment' must be a power of 2
    /// MUST be freed with freeAlignedToMarker()
    void* allocateAligned(const U32 byteSize, const U32 alignment);
        
    /// Set the stack top to a previous position
    void freeToMarker(const Marker marker);    
        
    void freeAlignedToMarker(const Marker marker);
    
    
    /// Return the stack size in bytes
    U32 getSize() { return m_byteSize; }

    /// Return a marker to the current stack top
    Marker getMarker() { return m_top; }
        
    /// Clear the stack, set the marker to zero
    void clear() { m_top = 0u; }
    

  private:
    DISALLOW_COPY_AND_ASSIGN(StackAllocator);
};
  
} // aer

#endif //AER_STACKALLOCATOR_HPP_
